之前有說到我們的代辦清單,每次都會重新來過。
所以啊!我們要把它存進我們的移動裝置裡。
這邊我們用的套件是sqflite
連結。
第一步,我們先建立我們的DB Class lib/db/todo_helper.dart
import 'package:sqflite/sqflite.dart' as sql;
import 'package:path/path.dart' as path;
import 'package:sqflite/sqlite_api.dart';
class DBHelper {
static Future<Database> database() async {
final dbPath = await sql.getDatabasesPath();
return sql.openDatabase(path.join(dbPath, 'todos.db'),
onCreate: (db, version) {
return db.execute(
'CREATE TABLE todo_list(id INTEGER PRIMARY KEY, groupId INTEGER, title TEXT, description TEXT, done INTEGER)');
}, version: 1);
}
static Future<void> insert(String table, Map<String, Object> data) async {
final db = await DBHelper.database();
db.insert(
table,
data,
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
static Future<void> update(String table, Map<String, Object> data) async {
final db = await DBHelper.database();
db.update(table, data, where: 'id = ?', whereArgs: [data['id']]);
}
static Future<void> delete(String table, Map<String, Object> data) async {
final db = await DBHelper.database();
db.delete(table, where: 'id = ?', whereArgs: [data['id']]);
}
static Future<List<Map<String, dynamic>>> getData(String table) async {
final db = await DBHelper.database();
return db.query(table);
}
}
這樣我們就可以正常使用我們的但辦清單DB了,然後看哪邊需要用到它。
就把它加進去。
主要要更改的地方,lib/providers/todos.dart
Class Todo with ChangeNotifier {
// ...
void toggleDone() {
done = !done;
notifyListeners();
DBHelper.update(
'todo_list',
{
'id': id,
'groupId': groupId,
'title': title,
'done': done,
'description': description,
},
);
}
Map<String, dynamic> toMap() {
return {
'id': id,
'groupId': groupId,
'title': title,
'description': description,
'done': done,
};
}
}
Class Todos with ChangeNotifier {
// ...
Future<void> fetchAndSetTodos() async {
final dataList = await DBHelper.getData('todo_list');
_items = dataList.map(
(item) {
print(item['done']);
return Todo(
id: item['id'],
groupId: item['groupId'],
title: item['title'],
description: item['description'],
done: item['done'] == 1 ? true : false,
);
},
).toList();
notifyListeners();
}
void addTodo(Todo todo) {
final newTodo = Todo(
title: todo.title,
description: todo.description,
done: false,
groupId: todo.groupId,
);
// _items.add(newTodo);
_items.insert(0, newTodo); // at the start of list
notifyListeners();
DBHelper.insert('todo_list', todo.toMap());
}
void deleteTodo(int itemId) {
final existingTodoIndex = _items.indexWhere((prod) => prod.id == itemId);
var existingTodo = _items[existingTodoIndex];
_items.removeAt(existingTodoIndex);
notifyListeners();
DBHelper.delete('todo_list', existingTodo.toMap());
}
// ...
}
再來,我們開啟代辦清單時,得要先跟SQLite拿資料,所以要到todos_homepage.dart
,把我們的fetchAndSetTodos()
放到該放的位置。
body: FutureBuilder(
future: Provider.of<Todos>(context, listen: false).fetchAndSetTodos(),
builder: (ctx, snapshot) => snapshot.connectionState ==
ConnectionState.waiting
? Center(
child: CircularProgressIndicator(),
)
: Consumer<Todos>(
child: Center(
child: const Text('Got no places yet, start adding some!'),
),
builder: (ctx, greatPlaces, ch) => greatPlaces.items.length <= 0
? ch
: ListView.builder(
itemCount: greatPlaces.getByGroupId.length,
itemBuilder: (ctx, i) => ChangeNotifierProvider.value(
value: greatPlaces.getByGroupId[i],
child:
TodoTile(slidableController: slidableController),
),
),
),
),
在 Scaffold -> body 我們包了一個 FutureBuilder
,讓我們可以非同步的跟SQLite要資料,
且可以知道是否還在Lodding,所以在這加上了 CircularProgressIndicator()
,提高使用者體驗。
明天繼續把群組也存進手機吧!